package com.zdp.leetcodeMiddle;
/*
* 题目描述：
* 有一个二维矩阵 A 其中每个元素的值为 0 或 1 。
移动是指选择任一行或列，并转换该行或列中的每一个值：将所有 0 都更改为 1，将所有 1 都更改为 0。
在做出任意次数的移动后，将该矩阵的每一行都按照二进制数来解释，矩阵的得分就是这些数字的总和。
返回尽可能高的分数。 
示例：
输入：[[0,0,1,1],[1,0,1,0],[1,1,0,0]]
输出：39
解释：
转换为 [[1,1,1,1],[1,0,0,1],[1,1,1,1]]
0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39
提示：
1 <= A.length <= 20
1 <= A[0].length <= 20
A[i][j] 是 0 或 1
来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/score-after-flipping-matrix
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
* */
public class 翻转矩阵后的得分 {
    public static void main(String[] args) {
        翻转矩阵后的得分 demo = new 翻转矩阵后的得分();
        System.out.println(demo.matrixScore(new int[][]{
                {0, 0, 1, 1}, {1, 0, 1, 0}, {1, 1, 0, 0}
        }));
    }
    public int matrixScore(int[][] A) {
       //因为要 最大的数，所以先将第一列全部变为1,进行行翻转  ----> 既然第一列一定为1了，那我还遍历它干啥，直接算值就完事了
        /*for(int i=0;i<A.length;i++){
            if(A[i][0]==0){
                for(int j=0;j<A[i].length;j++){ //行翻转
                    A[i][j] ^= 1;
                }
            }
        }*/
        int result = A.length * (1<<(A[0].length-1));
        //因为矩阵最左都为1了，所以现在只能进行列翻转，而列是否要进行翻转
        //则是要看一下列翻转是否能使数变大--->当该列0多于1时，进行翻转 ,我为什么要翻转呢，我直接记录一下就行了
        //记录每一列都有几个1
        //遍历列
        for(int i=1;i<A[0].length;i++){
            int oneNum = 0;
            for(int j=0;j<A.length;j++){
                //要先判断一下 该行有没有被翻转，翻转后1的数是不一样的
                if(A[j][0]==1){ //说明没有被翻转过
                    oneNum += A[j][i];
                }else{//有被翻转过 ,1为0，0为1
                    oneNum += 1-A[j][i];
                }
            }
            oneNum = Math.max(oneNum,A.length-oneNum); //判断是否需要列翻转
            //根据每一列1的个数，算出他们可以得到多少的值
            result += oneNum*(1<<(A[0].length-1-i));
        }
        return result;
    }
    /*
    * 记录一下自己最初愚蠢的做法，还傻傻地去多次遍历，去真的翻转，翻转完还一个一个算。。。
    * */
    public int matrixScore1(int[][] A) {
        //因为要 最大的数，所以先将第一列全部变为1,进行行翻转
        for(int i=0;i<A.length;i++){
            if(A[i][0]==0){
                for(int j=0;j<A[i].length;j++){ //行翻转
                    A[i][j] ^= 1;
                }
            }
        }
        //因为矩阵最左都为1了，所以现在只能进行列翻转，而列是否要进行翻转
        //则是要看一下列翻转是否能使数变大--->当该列0多于1时，进行翻转
        for(int i=1;i<A[0].length;i++){
            int count = 0;
            for(int j=0;j<A.length;j++){
                if(A[j][i]==1)
                    count++;
            }
            //如果0多于1 进行列翻转
            if(count<(A.length-count)){
                //进行列翻转
                for(int j=0;j<A.length;j++)
                    A[j][i] ^= 1;
            }
        }
        //计算值
        int result = 0;
        for(int i=0;i<A.length;i++){
            int num = 0;
            for(int j=0;j<A[0].length;j++){
                if(A[i][j]==1){
                    num += 1 << A[0].length-1-j;
                }
            }
            result +=num;
        }
        return result;
    }
}



